
/* Generated by Interface Builder */

#import "MotionView.h"
#import <appkit/Form.h>
#import <math.h>
#import <dpsclient/wraps.h>
#import "drawObjects.h"
#import <appkit/Application.h>


@implementation MotionView

void update (teNum, now, myself)
DPSTimedEntry teNum;
double now;
id myself;
{
    [myself doTimedEntry];        
}

+newFrame:(const NXRect *)tF {
    self = [super newFrame:tF];
    ballRadius = 8.0;
    ballDiameter = ballRadius*2.0;
    gravity = 0.1;
    angle = 45.0;
    force = 10.0;
    Dx = Dxi = 45.0;    // initial distance
    Dy = Dyi = 25.0;
    trail = 0;
	Vx = Vxi = sin((double) 3.14158/180 * angle) * force;
	Vy = Vyi = cos((double) 3.14158/180 * angle) * force;
	return self;
}

- setVxForm:anObject
{
    VxForm = anObject;
    return self;
}

- setVyForm:anObject
{
    VyForm = anObject;
    return self;
}

- initialize
{
	[self lockFocus]; 
    	NXEraseRect(&bounds);
    	PSsetgray(NX_BLACK);
	[self unlockFocus];
}

- start:sender
{
	if (!running) {
		running = 1;
    	clockTE = DPSAddTimedEntry(0.1, &update, self, NX_MODALRESPTHRESHOLD);
	}
    return self;
}

- stop:sender
{
	if (running) {
		running = 0;
    	DPSRemoveTimedEntry (clockTE);
	}
    return self;
}

- reset:sender
{
    if (running) {
    	running = 0;
    	DPSRemoveTimedEntry (clockTE);
	}
	Dx = Dxi;  Dy = Dxi;
	Vx = Vxi = sin((double) 3.14158/180 * angle) * force;
	Vy = Vyi = cos((double) 3.14158/180 * angle) * force;
	[VxForm setFloatValue:Vxi];
	[VyForm setFloatValue:Vyi];
	[self lockFocus]; 
    	NXEraseRect(&bounds);
    	PSsetgray(NX_BLACK);
	[self unlockFocus];

	[self display];
    return self;
}

- doTimedEntry
{
    Dx += Vx;
    Dy += Vy;

	[VxForm setFloatValue:Vx];
	[VyForm setFloatValue:Vy];
    
    // acceleration due to gravity    
    Vy -= gravity;
    
    // put in friction
    
    /* handle bouncing off the edges */
    if ((Dx > bounds.size.width - ballRadius) || (Dx < ballRadius)) Vx = -Vx;
    if ((Dy > bounds.size.height - ballRadius) ||(Dy < ballRadius)) Vy = -Vy;
	
	[self display];
    return self;
}

// Good programming practice. Free what you create!
- free
{
    [self stop:self];
    return [super free];
}

- speed:sender
{
	force = [sender floatValue];
	[self reset:self];
    return self;
}

- angle:sender
{
	angle = [sender floatValue];
	[self reset:self];
    return self;
}

- gravity:sender
{
	gravity = [sender floatValue];
	[self display];
    return self;
}

- trail:sender
{
	trail = [sender intValue];
	[self reset:self];
    return self;
}

- drawSelf:(NXRect*)r :(int)c
{
   	if (!trail) NXEraseRect(&bounds);
   	PSsetgray(NX_BLACK);
	drawPaddle(angle, force);
	doBall(Dx, Dy, ballRadius);
    return self;
}


@end
